﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpVersion_2
{
    class Exmaple_T
    {
        public static void Method()
        {
            List<int> numbers = new List<int>();
            numbers.Add(5);
            numbers.Add(10);
            numbers.Add(20);

            List<int> firstTwo = CopyAtMost<int>(numbers, 2);
            Console.WriteLine(firstTwo.Count);
        }

        /// <summary>
        /// 集合间的元素复制
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<T> CopyAtMost<T>(List<T> input, int maxElements)
        {
            int actualCount = Math.Min(input.Count, maxElements);
            List<T> ret = new List<T>(actualCount);
            for (int i = 0; i < actualCount; i++)
            {
                ret.Add(input[i]);
            }

            return ret;

        }


        /**
         * 类型约束
         * 不仅可以约束方法实参的值类型，也会约束方法内部如何操作和使用T类型的值
         * IFormattable接口方法：ToString(string, IFormatProvider)
        **/
        static void PrintItems<T>(List<T> items) where T: IFormattable
        {
            foreach (T item in items)
            {
                //编译器知道T实现Iformattable接口，
                //如果没有约束，编译将会报错，编译器只能找到System.Object下的Tostring
                //Console.WriteLine(item.ToString(null, new IFormatProvider()));
            }
        }

        /**
         * 类型约束不仅适用于接口，还可以约束一下类型：
         * 引用类型约束——where T : class. 类型实参必须是一个引用类型
         * 值类型约束——where T : struct. 类型实参必须是一个非空值类型
         * 构造器约束——where T : new().  类型实参必须是公共的无参构造器
         * 转换约束——where T : SomeType.    这里的someType可以是类、接口、或者其他形参
         *      ■ where T : Control
         *      ■ where T : IFormattable
         *      ■ where T1 : T2
         * 
         * */
         TResult Method<TArg, TResult>(TArg input) where TResult: class, new() where TArg: IComparable<TArg>
        {
            return null;
        }
    }
}
